iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
Kubernetes

初見 Kubernetes - 純網站後端開發踏入 K8s 世界的經驗分享系列 第 6

Day 6 - Worker Node 與 Pod 如何被啟動

  • 分享至 

  • xImage
  •  

昨天先從 Control Plane 了解 Kubernetes 如何接受 kubectl 指令、建立 Pod,並由 Scheduler 決定 Pod 要分派到哪一台 Node。今天主要會說明 Worker,以及當 Scheduler 已經選定一台 Node 之後,Pod 到底是如何在這台機器上被真正啟動的。

Worker Node 可以把它理解成 Kubernetes 實際承載工作負載的地方,像是後端 API、網站前端、Ingress,以及其他需要處理應用流量的服務,通常都會以 Pod 的形式運行在 Worker Node。而相對的,Control Plane 的資源應優先保留給 API Server、etcd、Scheduler 與 Controller Manager 等叢集管理元件,避免一般應用流量搶走維持叢集運作所需的資源。

但也不是說 Control Plane 絕對不能運行其他 Pod,只是在正式環境中,通常會透過 taint 與 toleration 去避免一般應用工作負載被 Scheduler 排入 Control Plane,這樣做能讓應用容量與叢集管理容量分開規劃,當應用流量增加時,主要考慮增加 Worker 的資源,不太需要優先考慮調整 Control Plane 的資源。

Worker Node 上有哪些重要角色?

當 Pod 被分派過來時,至少會有以下幾個角色接力處理:

元件 主要工作
kubelet 觀察 API Server 上已分派給自己的 Pod,並確保 Pod 按照 PodSpec 運作,也負責回報 Pod 狀態。
Container Runtime 透過 CRI 接收 kubelet 的要求,拉取 image、建立 Pod sandbox 與 container,並維持 container 的執行。
CNI Plugin 為 Pod 建立網路連線與 Pod IP,讓 Pod 能與叢集內其他工作負載及必要外部服務通訊。
kube-proxy 或 CNI 的資料平面實作 協助處理 Service 流量的轉送規則,不同 CNI 的實作方式可能不同。

https://ithelp.ithome.com.tw/upload/images/20260920/20124323nZpcpW5hus.png

今天會先聚焦 kubelet、Container Runtime 與 CNI 如何讓一個被排程的 Pod 從 存在於 API Server 的物件 變成真正執行的 container,Service、ClusterIP 與 DNS 的部分會在後續 Service 主題再說明。

kubelet

在 Day 5 提到,Scheduler 選定 Node 後,會透過 API Server 更新 Pod 的 binding,此時 kubelet 會透過 API Server 的 watch 機制看到「這個 Pod 已經指派給我」,並開始讓本機實際狀態符合 PodSpec。

kubelet 不會自行決定 Pod 該去哪台 Node,也不會直接讀寫 etcd,它主要負責在自己的 Node 上執行已被分派的 Pod,並將執行結果回報給 API Server,而 API Server 再將這些狀態寫入 etcd,供 Controller、kubectl 與其他元件觀察。

如果 kubelet 無法啟動 Pod,例如 image 無法拉取、Volume 無法掛載或 container 啟動後立即停止服務,這些狀態與事件都會逐步出現在 Kubernetes API 中,因此排查 Pod 問題時,kubectl describe pod 的 Events 與 kubectl logs 才會這麼重要。

Container Runtime

kubelet 知道 PodSpec 想要什麼,但它不直接處理 Linux 上建立 container 的細節,而是會透過 Container Runtime Interface(CRI) 向 Container Runtime 提出要求,常見的 Runtime 有 containerd 或 CRI-O。

收到要求後,Runtime 會取得需要的 image,並建立 Pod 所需的執行環境與 container。若 image 在 Node 本機不存在,就必須先從 Registry 拉取,因此 image 名稱、Registry 網路連線與拉取憑證,都可能成為 Pod 無法啟動的原因。

這也說明了 Kubernetes 中的分工:Scheduler 決定 Pod 在哪一個 Node 運作,kubelet 確保這台 Node 該跑什麼,Container Runtime 則處理如何在作業系統上將 container 跑起來。

CNI:Pod 在啟動後如何取得網路

container 已經啟動,還不代表服務能正常運作,因為 Pod 需要網路介面與 IP,才能對外或與其他 Pod 互通,
而 CNI(Container Network Interface)Plugin 就是在這個階段協助設定 Pod 網路。

不同 Kubernetes 版本或平台可能選用不同 CNI,因此底層路由、NetworkPolicy 與 Service 流量的實作不一定相同,不過要確認的事情我想都是一樣的:

  • Pod 是否取得預期網路設定
  • 是否能連到必要的下游服務
  • 網路規則是否放行需要的流量

Pod 的實際位置與可用資源,也會影響後續可用性設計,例如 Pod Anti-Affinity 則可讓同一服務 Pod 的 Replica 盡量分散到不同 Node,避免單一 Node 故障時同時失去多個 Pod,導致該服務的 Pod 全部被消失而影響整體系統運作。

從 Scheduler binding 到 Pod Running

將昨天與今天的內容串起來,一個 Pod 的啟動流程可以這樣理解:

  1. Scheduler 選定合適的 Worker Node,並透過 API Server 寫入 Pod 的 binding。
  2. API Server 將 binding 狀態寫到 etcd,目標 Node 的 kubelet 從 API Server watch 到這個 Pod。
  3. kubelet 讀取 PodSpec,準備必要的設定與 Volume,並透過 CRI 要求 Container Runtime 建立 Pod 的執行環境。
  4. Container Runtime 視需要拉取 image,建立並啟動 init container 與應用 container。
  5. CNI Plugin 為 Pod 設定網路;kubelet 持續取得 container 的實際狀態。
  6. kubelet 將 Pod 狀態更新到 API Server,API Server 再將狀態寫入 etcd。Controller 與維運人員便能看到 Pod 是否已進入 Running,或在哪個階段失敗。

https://ithelp.ithome.com.tw/upload/images/20260920/20124323T505dD4gw2.png

Worker 與 Pod 的資源配置

Worker Node 是提供 Pod 擁有的 CPU、Memory 等資源的主要來源,也因此 Worker 資源也會與 Pod 的 Replica 數量有相關,
只增加 Pod 副本卻沒有可用 Worker 資源,Pod 仍會停在 Pending;反過來說,如果 Worker 資源充足但應用沒有正確的副本策略,也有可能會讓 Worker 這些資源變成閒置資源而沒有好好利用。

所以 Worker 的資源配置其實比想像中複雜得多,或是應該說必須要實際蒐集好每個 Pod 的資源使用率,不論是在閒置、常態或是尖峰流量的情境,
甚至如果有 Auto Scaler 的需求,那要評估與測試的工作也會變得更多,
而不是一昧的增加 Worker 、Pod 的資源或數量。

結論

Worker Node 是 Kubernetes 將接收到的指令轉為實際服務的執行角色。Scheduler 完成分派後,kubelet 會發現屬於自己的 Pod,透過 CRI 指示 Container Runtime 建立 container,再由 CNI 完成 Pod 網路設定;最後 kubelet 將實際狀態回報給 API Server 並更新到 etcd。

理解這條流程後,往後遇到 PendingImagePullBackOffCrashLoopBackOff 或 Pod 無法接收流量時,就能知道問題可能落在排程、kubelet、image、Volume、網路、container 或 readiness 的哪一個環節,排錯的方向也會比較清楚,進而降低花費的時間。


上一篇
Day 5 - Control Plane 與四大元件
下一篇
Day 7 - CRI、CNI、CSI 三種介面與用途
系列文
初見 Kubernetes - 純網站後端開發踏入 K8s 世界的經驗分享9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言